package controller

import (
	"bytes"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"golang.org/x/net/context"
	"io"
	"ksd-social-api/commons/base/controller"
	"ksd-social-api/commons/tools"
	"ksd-social-api/utils"
	"ksd-social-api/utils/rdb"
	"net/http"
	"sort"
	"strings"
	"time"
)

type WxGZHLoginController struct {
	controller.BaseController
}

var (
	TOKEN string = "familySchool"
)

/*
获取微信公众号登录二维码
*/
func (web *WxGZHLoginController) GetQRCode() {
	// 根据appid缓存accessToken
	// 1： 获取 Access token
	token_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s", "client_credential", "wxdb501f501bc9507d", "d627242ab7137b623254a8994ce6ab12")
	resp, _ := http.Get(token_url)
	body, _ := io.ReadAll(resp.Body)
	toMap := utils.JsonToMap((string(body)))
	// 2： 根据 Access token 获取登录二维码
	accessToken := toMap["access_token"]

	create_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken)
	sceneMap := map[string]any{}
	actionInfo := map[string]any{}
	bodyMap := make(map[string]any)

	nonce, _ := tools.GenerateNonce()
	sceneMap["scene_str"] = nonce
	actionInfo["scene"] = sceneMap
	bodyMap["action_info"] = actionInfo
	bodyMap["expire_seconds"] = 300
	bodyMap["action_name"] = "QR_SCENE"

	bytesData, _ := json.Marshal(bodyMap)
	client := &http.Client{}
	request, err := http.NewRequestWithContext(context.Background(), http.MethodPost, create_url, bytes.NewReader(bytesData))
	fmt.Println(err)
	request.Header.Set("Content-Type", "application/json")
	resp2, _ := client.Do(request)
	body2, _ := io.ReadAll(resp2.Body)
	toMap2 := utils.JsonToMap((string(body2)))

	ticket := toMap2["ticket"]
	resp3, _ := http.Get(fmt.Sprintf("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s", ticket))
	body3, _ := io.ReadAll(resp3.Body)
	encoding := base64.StdEncoding
	toString := encoding.EncodeToString(body3)
	rdb.RdbSetEX(fmt.Sprintf("cc:%s", ticket), ticket, 280)

	defer resp3.Body.Close()
	defer resp2.Body.Close()
	defer resp.Body.Close()
	resultMap := map[string]any{}
	resultMap["ticket"] = ticket
	resultMap["img"] = toString
	web.Ok(resultMap)
}

type TextMessage struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string   `xml:"ToUserName"`
	FromUserName string   `xml:"FromUserName"`
	CreateTime   int64    `xml:"CreateTime"`
	MsgType      string   `xml:"MsgType"`
	Content      string   `xml:"Content"`
}

type ResponseMessage struct {
	XMLName      xml.Name `xml:"xml"`
	ToUserName   string   `xml:"ToUserName"`
	FromUserName string   `xml:"FromUserName"`
	CreateTime   int64    `xml:"CreateTime"`
	MsgType      string   `xml:"MsgType"`
	Content      string   `xml:"Content"`
}

/*
扫码登录成功获取openId
*/
func (web *WxGZHLoginController) Callback() {
	// 1： 获取 Access token
	// 2： 根据 Access token 获取登录二维码
	signature := web.GetString("signature")
	timestamp := web.GetString("timestamp")
	nonce := web.GetString("nonce")
	//echostr := web.GetString("echostr")
	if !web.checkSignature(signature, timestamp, nonce) {
		web.FailCodeMsg(601, "微信回调参数异常")
		return
	}

	stringMap := make(map[string]string)
	xml.Unmarshal(web.Ctx.Input.RequestBody, (*utils.StringMap)(&stringMap))

	ticket := stringMap["Ticket"]          // 获取二维码凭证
	gzhOpenid := stringMap["FromUserName"] // 获取OpenId
	eventType := stringMap["Event"]        // 获取事件类型
	rdb.RdbDel("cc:" + ticket)
	rdb.RdbSetEX("cc:openid:"+ticket, gzhOpenid, 280)
	if strings.EqualFold("subscribe", eventType) { // 如果是订阅消息
		subscribeContent := "感谢关注"
		rdb.RdbSetEX("cc:gz:"+ticket, "0", 280)
		// 创建回复消息
		response := &ResponseMessage{
			ToUserName:   stringMap["FromUserName"],
			FromUserName: stringMap["ToUserName"],
			CreateTime:   time.Now().Unix(),
			MsgType:      "text",
			Content:      "你发送的消息是：" + subscribeContent,
		}
		xmlStr, _ := xml.Marshal(response)
		web.Ctx.ResponseWriter.Write([]byte(string(xmlStr)))
		return
	}
	if strings.EqualFold("SCAN", eventType) { //  如果是扫码消息
		scanContent := "扫码成功"
		rdb.RdbSetEX("cc:saoma:"+ticket, "0", 280)
		// 创建回复消息
		response := &ResponseMessage{
			ToUserName:   stringMap["FromUserName"],
			FromUserName: stringMap["ToUserName"],
			CreateTime:   time.Now().Unix(),
			MsgType:      "text",
			Content:      "你发送的消息是：" + scanContent,
		}
		xmlStr, _ := xml.Marshal(response)
		web.Ctx.ResponseWriter.Write([]byte(string(xmlStr)))
		return
	}

	web.FailCodeMsg(601, "xxxx")
}

/*
扫码登录成功获取openId
*/
func (web *WxGZHLoginController) Auth() {
	signature := web.GetString("signature")
	timestamp := web.GetString("timestamp")
	nonce := web.GetString("nonce")
	echostr := web.GetString("echostr")
	if web.checkSignature(signature, timestamp, nonce) {
		fmt.Sprintf("数据源为微信后台，将echostr[%s]返回！", echostr)
		web.Ctx.WriteString(echostr)
	}
}

func (web *WxGZHLoginController) checkSignature(signature, timestamp, nonce string) bool {
	array := []string{nonce, timestamp, TOKEN} // token 为微信开发者平台上提交的字符串
	sort.Sort(sort.StringSlice(array))
	tmpStr := string(array[0] + array[1] + array[2])
	data := []byte(tmpStr)
	hash := sha1.Sum(data)
	chkStr := hex.EncodeToString(hash[0:20])
	if chkStr != signature {
		return false
	}
	return true
}

/*
轮询扫码登录成功获取openId是否成功，如果成功直接注册或者登录
*/
func (web *WxGZHLoginController) ChecKLogin() {
	// 1： 获取 Access token
	// 2： 根据 Access token 获取登录二维码
	web.Ok("success")
}
